Shader "Unlit/IVGI_Demo"
{
    Properties
    {
        _MainTex ("_MainTex", 2D) = "white" {}
        _Color ("_Color", Color) = (0,0,0,0)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "LightMode"="UniversalForward" }
        LOD 100

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "./IrradianceVolumeGI.hlsl"

            struct Attributes
            {
                float4 positionOS : POSITION;
                float3 normalOS : NORMAL;
                float2 uv : TEXCOORD0;
            };

            struct Varings
            {
                float4 positionCS : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 positionWS : TEXCOORD1;
                float3 normalWS : TEXCOORD2;
                float3 viewDirWS : TEXCOORD3;
                float4 SHParamR : TEXCOORD4;
                float4 SHParamG : TEXCOORD5;
                float4 SHParamB : TEXCOORD6;
            };

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            float4 _MainTex_ST;
            float3 _CenterPosition;
            int _DataIndex;
            bool _OnlyColor;
            float4 _Color;
            
            bool _UseLightProbe_Full;
            bool _UseLightProbe_L0L1;
            bool _UseLightProbe_L1;
            bool _UseLightProbe_L0;

            bool _Use_IVGI_L0L1;
            bool _Use_IVGI_L1;

            bool _Use_IVGI_L0L1_Tex;
            bool _Use_IVGI_L1_Tex;

            real3 SHEvalLinearL0L1xxxx(real3 N, real4 shAr, real4 shAg, real4 shAb)
            {
                real4 vA = real4(N, 1.0);

                real3 x1;
                // Linear (L1) + constant (L0) polynomial terms
                x1.r = dot(float4(0,shAr.g,0,0), vA);
                x1.g = dot(float4(0,shAg.g,0,0), vA);
                x1.b = dot(float4(0,shAb.g,0,0), vA);

                return x1;
            }
            
            Varings vert (Attributes IN)
            {
                Varings OUT;
                // GPU Instancing
                // UNITY_SETUP_INSTANCE_ID(IN);
                // UNITY_TRANSFER_INSTANCE_ID(IN, OUT);
                
                VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz);
                VertexNormalInputs normalInputs = GetVertexNormalInputs(IN.normalOS.xyz);
                //OUT.positionCS = TransformObjectToHClip(IN.positionOS);
                OUT.positionCS = positionInputs.positionCS;
                OUT.positionWS =  positionInputs.positionWS; 
                OUT.viewDirWS = GetCameraPositionWS() - positionInputs.positionWS;
                OUT.normalWS = normalInputs.normalWS;
                OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);
                //OUT.color = SampleIVGI(OUT.positionWS.xyz,OUT.normalWS.xyz);

                if (_Use_IVGI_L0L1_Tex)
                {
                    float3 SHL0, SHL1;
                    UnpackSHL0L1_Tex(OUT.positionWS,OUT.normalWS, SHL0, SHL1);
                    //UnpackSHL0L1_Tex(_CenterPosition, SHL0, SHL1);
                    
                    float4 shAr, shAg, shAb;
                    ReconstructSHCoefficient(SHL0, SHL1,shAr, shAg, shAb);
                
                    OUT.SHParamR = shAr;
                    OUT.SHParamG = shAg;
                    OUT.SHParamB = shAb;
                }
                
                return OUT;
            }
            
            float4 frag (Varings IN) : SV_Target
            {
                // if (_OnlyColor)
                // {
                //     //return float4(_IVGIDataBuffer_Luminance[_DataIndex],1);
                //     return _Color;
                // }

                //return IN.normalWS.xyzz;
                
                float3 indirect = 0;
                
                real4 SHCoefficients[7];
                SHCoefficients[0] = unity_SHAr;
                SHCoefficients[1] = unity_SHAg;
                SHCoefficients[2] = unity_SHAb;
                SHCoefficients[3] = unity_SHBr;
                SHCoefficients[4] = unity_SHBg;
                SHCoefficients[5] = unity_SHBb;
                SHCoefficients[6] = unity_SHC;
                
                if (_UseLightProbe_Full)
                {
                    indirect = float4(SampleSH9(SHCoefficients, IN.normalWS), 1);
                }

                if (_UseLightProbe_L0L1)
                {
                    indirect = float4(SHEvalLinearL0L1(IN.normalWS, unity_SHAr, unity_SHAg, unity_SHAb), 1);
                }

                if (_UseLightProbe_L0)
                {
                    indirect = float4(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w, 1);
                }

                if (_UseLightProbe_L1)
                {
                    indirect = float4(SHEvalLinearL1(IN.normalWS, unity_SHAr, unity_SHAg, unity_SHAb), 1);
                }

                // light
                float4 shadowCoord = TransformWorldToShadowCoord(IN.positionWS.xyz);
                Light light = GetMainLight();
                float3 lightDirWS = light.direction;
                float3 lightColor = light.color;
                float lightIntensity = light.distanceAttenuation;

                if (_Use_IVGI_L1)
                {
                    float4 shAr;
                    float4 shAg;
                    float4 shAb;
                    ReconstructSHCoefficient(_IVGIDataBuffer_L0[_DataIndex], _IVGIDataBuffer_Luminance[_DataIndex], shAr,shAg, shAb);

                    const float4 SHValue_L0L1R = EvalSHTwoBand(IN.normalWS);
                    float3 Result;
                    Result.r = dot(SHValue_L0L1R.xyz, shAr);
                    Result.g = dot(SHValue_L0L1R.xyz, shAg);
                    Result.b = dot(SHValue_L0L1R.xyz, shAb);
                    return float4(Result, 1);
                }
  
                if (_Use_IVGI_L0L1)
                {
                    indirect = SampleIVGI(IN.positionWS.xyz, IN.normalWS.xyz);
                }

                if (_Use_IVGI_L1_Tex)
                {
                    
                }

                if (_Use_IVGI_L0L1_Tex)
                {
                    //indirect = SampleIVGI_Tex(_CenterPosition, IN.normalWS);
                    indirect = SampleIVGI_Tex(IN.positionWS, IN.normalWS);
				    //indirect = SHEvalLinearL0L1(IN.normalWS, IN.SHParamR, IN.SHParamG, IN.SHParamB);
                }
                
                return float4(indirect, 1);
            }
            ENDHLSL
        }
    }
}
